/*----------------------------------------------------------------------------*/
/* Copyright 2011 http://www.kmftech.com                                      */
/*                                                                            */
/* This file is part of kmftech.                                              */
/*                                                                            */
/* kmftech is free software: you can redistribute it and/or modify it under   */
/* the terms of the GNU General Public License as published by the Free       */
/* Software Foundation, version 2 of the License, or (at your option) any     */
/* later version.                                                             */
/*                                                                            */
/* kmftech is distributed in the hope that it will be useful, but WITHOUT ANY */
/* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  */
/* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more      */
/* details.                                                                   */
/*                                                                            */
/* You should have received a copy of the GNU General Public License along    */
/* with kmftech. If not, see http://www.gnu.org/licenses/.                    */
/*----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------*/
/*---------------------------- DOCUMENT HISTORY ------------------------------*/
/* Ver: 1.0    Author: Karim Mansour                      Date: 30 April 2011 */
/* Ver: 1.1    Author: Karim Mansour                      Date: 28 May 2011   */
/* Ver: 1.2    Author: Karim Mansour                      Date: 06 June 2011  */
/* Ver: 1.3    Author: Karim Mansour                      Date: 08 June 2011  */
/* Ver: X.X    Author:                                    Date:               */
/*----------------------------------------------------------------------------*/
/*---------------------    DOCUMENT CHANGE HISTORY ---------------------------*/
/* Ver: 1.0    Change: Initial Version.                                       */
/* Ver: 1.1    Change: Merged bsc header files to one header file             */
/* Ver: 1.2    Change: replaced the contents of the 1s and 4s tasks           */
/* Ver: 1.3    Change: Removed application function from tasks (Disable RTOS) */
/* Ver: X.X    Change:                                                        */
/*----------------------------------------------------------------------------*/


/*                           Needed Header Files                              */
#include "kmftech_types.h"
#include "bsc.h"
#include "app_main.h"


/*                         RTOS Global Declarations                           */
#define CPU_CLK_FREQUENCY (16000000)
#define CPU_CLK_DIVISOR (8)
#define RTOS_TIMER_MAX (255)
#define TICK_IN_US (5000)
#define TICK_IN_MS (TICK_IN_US/1000)
#define TICK_TRIGGER (((CPU_CLK_FREQUENCY / CPU_CLK_DIVISOR) / 1000000) * \
                     TICK_IN_US) /RTOS_TIMER_MAX

/*Number of tasks*/
#define TASKS_NB (10)

/* Tasks states*/
#define IDLE     (0x00)
#define READY    (0x01)
#define RUNNING  (0x02)
#define ERROR    (0x03)

/*Pointer to function that points to the RTOS tasks*/
typedef void (*pf_task)(void);

/*Task Block*/
typedef struct str_task_block_template
{
   /*Task ID*/
   uint8 u8_id;
   /*Pointer to the task*/
   pf_task pf_task_fn;
   /*Time left before execution*/
   uint16 u16_time_left; 
   /*Task period*/
   uint16 u16_period;
   /*Task status*/
   uint8 u8_status;
} str_rtos_task_block;

/*Array of tasks*/
str_rtos_task_block arr_str_rtos_task_block[TASKS_NB];

/*RTOS system counter*/
uint32 u32_rtos_sys_counter = 0;

/*                           Functions Prototypes                             */
void vd_rtos_init(void);
void vd_rtos_add_task(uint8 u8_task_id,
                      pf_task pf_fn_name,
                      uint16 u16_task_period);
void vd_rtos_remove_task(uint8 u8_task_id);
uint8 u8_rtos_get_task_status(uint8 u8_task_id);
void vd_rtos_run_tasks(void);
void vd_rtos_tick_generator(void);
void vd_task_5ms(void);
void vd_task_10ms(void);
void vd_task_50ms(void);
void vd_task_100ms(void);
void vd_task_1000ms(void);
void vd_task_4000ms(void);
void vd_rtos_start(void);


/*                         Functions Implementation                           */

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_rtos_init                                                  */
/* Description: Initialize kmftech RTOS                                       */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_rtos_init(void)
{
   /*Use Timer(8bits 1) and let it counts using 1/8 of the clock frequency    */
   vd_bsc_timer_set_clk_div(8,1,8);
   /*Set initial value (0) to Timer(8bits 1)                                  */
   vd_bsc_timer_set_val(8,1,0);
   /*Enable overflow interrupt for Timer(8bits 1)*/
   vd_bsc_timer_int_ovf_enable(8,1);

   /*Initialize the RTOS tasks blocks*/
   uint8 u8_index;
   for(u8_index=0; u8_index<TASKS_NB; u8_index++)
   {
      arr_str_rtos_task_block[u8_index].u8_id = 0;
      arr_str_rtos_task_block[u8_index].pf_task_fn = (pf_task)0x00;
      arr_str_rtos_task_block[u8_index].u16_time_left = 0;
      arr_str_rtos_task_block[u8_index].u16_period = 0;
      arr_str_rtos_task_block[u8_index].u8_status = IDLE;
    }
    vd_rtos_add_task(1,vd_task_5ms, 5/TICK_IN_MS);
    vd_rtos_add_task(2,vd_task_10ms, 10/TICK_IN_MS);
    vd_rtos_add_task(3,vd_task_50ms, 50/TICK_IN_MS);
    vd_rtos_add_task(4,vd_task_100ms, 100/TICK_IN_MS);
    vd_rtos_add_task(5,vd_task_1000ms, 1000/TICK_IN_MS);
    vd_rtos_add_task(6,vd_task_4000ms, 4000/TICK_IN_MS);
}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_rtos_add_task                                              */
/* Description: Add task to kmftech RTOS                                      */
/* Input(s)   : Input  1: uint8 - Task ID                                     */
/*            : Input  2: pf_task - Task Function                             */
/*            : Input  3: uint16 - Task period                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_rtos_add_task(uint8 u8_task_id,
                      pf_task pf_fn_name,
                      uint16 u16_task_period)
{
   uint8 u8_index = 0;
   for (u8_index=0; u8_index < TASKS_NB; u8_index++)
   {
      if(arr_str_rtos_task_block[u8_index].u8_status == IDLE)
      {
         arr_str_rtos_task_block[u8_index].u8_id = u8_task_id;
         arr_str_rtos_task_block[u8_index].pf_task_fn = pf_fn_name;
         arr_str_rtos_task_block[u8_index].u16_time_left = u16_task_period;
         arr_str_rtos_task_block[u8_index].u16_period = u16_task_period;
         arr_str_rtos_task_block[u8_index].u8_status = READY;
         break;
      }
   }
}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_rtos_remove_task                                           */
/* Description: Remove task from kmftech RTOS                                 */
/* Input(s)   : Input  1: uint8 - Task ID                                     */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_rtos_remove_task(uint8 u8_task_id)
{
   uint8 u8_index;
   for(u8_index=0; u8_index < TASKS_NB; u8_index++)
   {
      if(arr_str_rtos_task_block[u8_index].u8_id == u8_task_id)
      {
         arr_str_rtos_task_block[u8_index].u8_status = IDLE;
         break;
      }
   }
}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : u8_rtos_get_task_status                                       */
/* Description: Remove task from kmftech RTOS                                 */
/* Input(s)   : Input  1: uint8 - Task ID                                     */
/* Output(s)  : Output 1: uint8 - Task status                                 */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
uint8 u8_rtos_get_task_status(uint8 u8_task_id)
{
   uint8 u8_index;
   for(u8_index=0; u8_index < TASKS_NB; u8_index++)
   {
      if(arr_str_rtos_task_block[u8_index].u8_id == u8_task_id)
      {
         return arr_str_rtos_task_block[u8_index].u8_status;
      }
   }
   return ERROR;
}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_rtos_run_tasks                                             */
/* Description: Remove task from kmftech RTOS                                 */
/* Input(s)   : Input  1: uint8 - Task ID                                     */
/* Output(s)  : Output 1: uint8 - Task status                                 */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_rtos_run_tasks(void)
{
   uint8 u8_index;
    for(u8_index=0; u8_index < TASKS_NB; u8_index++)
    {
        /*Search for a READY task that is ready to run*/
        if( !arr_str_rtos_task_block[u8_index].u16_time_left &&
             arr_str_rtos_task_block[u8_index].u8_status == READY )
        {
            /*Task found, and it is now RUNNING*/
            arr_str_rtos_task_block[u8_index].u8_status = RUNNING;
            /*Call the task function*/
            (*arr_str_rtos_task_block[u8_index].pf_task_fn)();
            /*Reset time left to task period*/
            arr_str_rtos_task_block[u8_index].u16_time_left =
                                   arr_str_rtos_task_block[u8_index].u16_period;
            /*The task has finished and it is READY to run again in its time*/
            arr_str_rtos_task_block[u8_index].u8_status = READY;
        }
    }
}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_rtos_tick_generator                                        */
/* Description: Generates RTOS ticks                                          */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_rtos_tick_generator(void)
{
   u32_rtos_sys_counter ++;
   if(u32_rtos_sys_counter == TICK_TRIGGER)
   {
      /*Tick generated*/
      /*Reset rtos sys counter*/
      u32_rtos_sys_counter = 0;
      /*Search for READY tasks and decrease its time_left parameter*/
      uint8 u8_index;
      for(u8_index=0; u8_index < TASKS_NB; u8_index++)
      {
         if(arr_str_rtos_task_block[u8_index].u8_status == READY)
         arr_str_rtos_task_block[u8_index].u16_time_left--;
      }
   }
}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_task_5ms                                                   */
/* Description: Task that runs every 5ms                                      */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_task_5ms(void)
{

}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_task_10ms                                                  */
/* Description: Task that runs every 10ms                                     */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_task_10ms(void)
{

}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_task_50ms                                                  */
/* Description: Task that runs every 50ms                                     */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_task_50ms(void)
{

}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_task_100ms                                                 */
/* Description: Task that runs every 100ms                                    */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_task_100ms(void)
{

}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_task_1000ms                                                */
/* Description: Task that runs every 1000ms                                   */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_task_1000ms(void)
{
   
}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_task_4000ms                                                */
/* Description: Task that runs every 4000ms                                   */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_task_4000ms(void)
{

}

/*----------------------------------------------------------------------------*/
/*---------------------------- FUNCTION HEADER -------------------------------*/
/* Name       : vd_rtos_start                                                 */
/* Description: Start kmftech RTOS                                            */
/* Input(s)   : Input  1: void                                                */
/* Output(s)  : Output 1: void                                                */
/* Author     : Karim Mansour                                                 */
/*----------------------------------------------------------------------------*/
void vd_rtos_start(void)
{
   while(1)
   {
      vd_rtos_run_tasks();
   }
}



/*-----------------------------End Of File------------------------------------*/
